home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_053 / tarsplit / tarsplit.c < prev   
C/C++ Source or Header  |  1992-05-06  |  4KB  |  206 lines

  1. /*
  2.  * TarSplit -- split up tar files (creating directories as needed)
  3.  *
  4.  * usage: TarSplit [pathname]
  5.  *
  6.  * semantics: splits up tar file taken from stdin (or pathname, if
  7.  * specified) and creates the files therein under the working data
  8.  * directory.
  9.  */
  10.  
  11. #include <stdio.h>
  12.  
  13. #ifdef    AMIGA
  14. #include <exec/types.h>
  15. typedef    int    bool ;
  16. bool    ChkSumOK() ;
  17. #include <libraries/dosextens.h>
  18. #else
  19. #include <modes.h>
  20. #include <bool.h>
  21. #define DIRMODE        (S_IREAD | S_IWRITE | S_IEXEC | S_IOREAD | S_IOEXEC)
  22. #endif
  23. #define TBLOCK    512
  24. #define NAMSIZ    100
  25.  
  26. union hblock {
  27.     char dummy[TBLOCK];
  28.     struct header {
  29.         char name[NAMSIZ];
  30.         char mode[8];
  31.         char uid[8];
  32.         char gid[8];
  33.         char size[12];
  34.         char mtime[12];
  35.         char chksum[8];
  36.         char linkflag;
  37.         char linkname[NAMSIZ];
  38.     } dbuf;
  39. };
  40.  
  41. #define BLKSIZE        (sizeof (union hblock))
  42. #define HARDLINK    '1'
  43. #define SYMBLINK    '2'
  44. #define NORMAL        '\0'
  45.  
  46. main(argc, argv)
  47. int    argc;
  48. char    *argv[];
  49. {
  50.     FILE        *TarFP;
  51.     union hblock    TarBlock;
  52.  
  53. #ifndef    AMIGA
  54.     /* make the compiler happy about formatted I/O for longs... */
  55.     pflinit();
  56. #endif
  57.  
  58.     switch(argc) {
  59. #ifndef    AMIGA
  60.     case 1:
  61.         TarFP = stdin;
  62.         break;
  63. #endif
  64.     case 2:
  65.         if ((TarFP = fopen(argv[1], "r")) == NULL) {
  66.             fprintf(stderr, "TarSplit: can't open %s\n", argv[1]);
  67.             exit(1);
  68.         }
  69.         break;
  70.     default:
  71.         fprintf(stderr, "usage: TarSplit [pathname]\n");
  72.         exit(1);
  73.     }
  74.  
  75.     for (;;) {
  76.         if (fread(&TarBlock, BLKSIZE, 1, TarFP) == NULL) {
  77.             fprintf(stderr, "TarSplit: premature EOF\n");
  78.             exit(1);
  79.         } else if (IsZero(&TarBlock)) {
  80.             while (fread(&TarBlock, BLKSIZE, 1, TarFP) != NULL)
  81.                 ;
  82.             break;
  83.         } else
  84.             DoFile(&TarBlock, TarFP);
  85.     }
  86.  
  87. }
  88.  
  89. bool
  90. IsZero(block)
  91. union hblock    *block;
  92. {
  93.     int    i;
  94.     char    *cblock;
  95.  
  96.     cblock = block->dummy;
  97.     for (i = 0; i < TBLOCK; i++)
  98.         if (*cblock++ != '\0')
  99.             return(FALSE);
  100.  
  101.     return (TRUE);
  102.  
  103. }
  104.  
  105. DoFile(block, TarFP)
  106. union hblock    *block;
  107. FILE        *TarFP;
  108. {
  109.     long    FSize;
  110.     char    FName[NAMSIZ], *RefName;
  111.     int    i;
  112.     bool    IsDir, OpenOK;
  113.     FILE    *NewFP;
  114.  
  115.     if (!ChkSumOK(block)) {
  116.         fprintf(stderr, "TarSplit: bad checksum, name %s?\n",
  117.             block->dbuf.name);
  118.         exit(1);
  119.     }
  120.  
  121.     switch(block->dbuf.linkflag) {
  122.     case HARDLINK:
  123.     case SYMBLINK:
  124.         fprintf(stderr, "TarSplit: can't handle links\n");
  125.         exit(1);
  126.     case NORMAL:
  127.         break;
  128.     default:
  129.         fprintf(stderr, "TarSplit: unknown linkflag\n");
  130.         exit(1);
  131.     }
  132.  
  133. #ifdef    AMIGA
  134.     if (sscanf(block->dbuf.size, "%12lo", &FSize) != 1) {
  135. #else
  136.     if (sscanf(block->dbuf.size, "%12O", &FSize) != 1) {
  137. #endif
  138.         fprintf(stderr, "TarSplit: bad size\n");
  139.         exit(1);
  140.     }
  141.  
  142.     for (i = 0, RefName = block->dbuf.name; *RefName; i++, RefName++)
  143.         FName[i] = *RefName;
  144.  
  145.     if (IsDir = (*(RefName - 1) == '/')) {
  146.         FName[i - 1] = '\0';
  147.         if (strcmp(FName, ".") == 0)
  148.             OpenOK = TRUE;
  149.         else
  150. #ifdef    AMIGA
  151.             {
  152.             struct FileLock *Lock, *CreateDir() ;
  153.             OpenOK = (Lock = CreateDir(FName)) != 0 ;
  154.             UnLock(Lock) ;
  155.             }
  156. #else
  157.             OpenOK = mknod(FName, DIRMODE) == 0;
  158. #endif
  159.     } else {
  160.         FName[i] = '\0';
  161.         OpenOK = (NewFP = fopen(FName, "w")) != NULL;
  162.     }
  163.  
  164.     if (!OpenOK) {
  165.         fprintf(stderr, "TarSplit: can't create %s\n", FName);
  166.         exit(1);
  167.     }
  168.  
  169.     for (; FSize > 0; FSize -= TBLOCK) {
  170.         if (fread(block, BLKSIZE, 1, TarFP) == NULL) {
  171.             fprintf(stderr, "TarSplit: premature EOF\n");
  172.             exit(1);
  173.         }
  174.         if (!IsDir)
  175.             fwrite(block->dummy, 1,
  176.                 (FSize > TBLOCK ? TBLOCK : (int) FSize), NewFP);
  177.     }
  178.  
  179.     if (!IsDir)
  180.         fclose(NewFP);
  181.  
  182. }
  183.  
  184. bool
  185. ChkSumOK(block)
  186. union hblock    *block;
  187. {
  188.     long    Accum, ChkSumVal;
  189.     int    i;
  190.  
  191. #ifdef    AMIGA
  192.     sscanf(block->dbuf.chksum, "%8lo", &ChkSumVal);
  193. #else
  194.     sscanf(block->dbuf.chksum, "%8O", &ChkSumVal);
  195. #endif
  196.     for (i = 0; i < 8; i++)
  197.         block->dbuf.chksum[i] = ' ';
  198.  
  199.     Accum = 0;
  200.     for (i = 0; i < TBLOCK; i++)
  201.         Accum += 0xff & block->dummy[i];
  202.  
  203.     return(Accum == ChkSumVal);
  204.  
  205. }
  206.